// 我们在后台管理系统，一定会有大量的表格，表格一定有功能 ： 初始数据 ， 搜索 ， 分页
// 把这个逻辑进行一个封装复用
interface MyResponse<T> {
  code: number;
  data: T;
  message: string;
}

type RSP<T> = Promise<MyResponse<T>>;

interface TableResponse<T> {
  list: T[];
  total: number;
  totalPage: number;
  pageNum: number;
  pageSize: number;
}

import { reactive, ref, toRefs, watch } from "vue";

// 所有的逻辑 都差不多，只有 请求的函数 + 搜索的参数 在变 ， 所以我们把这两个 变成参数
export default function useTable<T>(
  apiFunc: (...params: any) => RSP<TableResponse<T>>,
  searchParams: Object
) {
  // 声明一个参数，里面默认有 分页的参数
  let queryParams = reactive({
    pageNum: 1,
    pageSize: 10,
  });

  // 必然有一个数据数组
  const list = ref<T[]>([]);
  // 还有一个总条数
  const total = ref(0);

  // 取消功能
  let controller: AbortController;
  let isFetching = false;

  function request() {
    isFetching = true;
    controller = new AbortController();
    apiFunc(Object.assign({}, queryParams, searchParams), controller.signal)
      .then((res) => {
        if (res.code === 200) {
          // 把数据存起来
          // @ts-ignore
          list.value = res.data.list;
          total.value = res.data.total;
        }
      })
      .finally(() => {
        isFetching = false;
      });
  }
  // 必然会一开始的时候先请求一次数据
  request();

  // 必然有分页
  const { pageNum, pageSize } = toRefs(queryParams);
  watch([pageNum, pageSize], () => {
    // 如果已经有 上一次请求
    if (isFetching) {
      controller.abort();
    }
    request();
  });

  // 把外面需要的数据，暴露出去
  return {
    list,
    total,
    pageNum,
    pageSize,
    request,
  };
}
